package Server.serviceRegister.impl;

import Server.serviceRegister.ServiceRegister;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

import java.net.InetSocketAddress;

public class ZKServiceRegister implements ServiceRegister {

    // curator提供的zookeeper客户端
    private CuratorFramework client;
    // zookeeper根路径节点
    private static final String ROOT_PATH = "MyRPC";
    private static final String RETRY = "CanRetry";

    // zookeeper客户端初始化，并连接zookeeper
    public ZKServiceRegister() {
        // 指数时间重试
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        this.client = CuratorFrameworkFactory.builder()
                .connectString("127.0.0.1:2181")
                .sessionTimeoutMs(40000)
                .namespace(ROOT_PATH)
                .retryPolicy(retryPolicy)
                .build();
        this.client.start();
        System.out.println("zookeeper连接成功");
    }

    @Override
    public void register(String serviceName, InetSocketAddress inetSocketAddress, boolean canRetry) {
        try {
            // 如果serviceName创建成永久节点，服务提供者下线时，不删除服务名只删除地址
            if ((client.checkExists().forPath("/" + serviceName) == null)) {
                client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/" + serviceName);
            }
            // 路径的地址，1个/表示1个节点
            String servicePath = "/" + serviceName + "/" + getServiceAddress(inetSocketAddress);
            // 临时节点，服务器下线就删除节点
            client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(servicePath);
            // 如果服务幂等，就添加到节点中
            if (canRetry) {
                servicePath = "/" + RETRY + "/" + serviceName;
                client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(servicePath);
            }
        } catch (Exception e) {
            System.out.println("此服务已经存在");
        }
    }

    // 地址 -> XXX.XXX.XXX.XXX:port 字符串
    private String getServiceAddress(InetSocketAddress inetSocketAddress) {
        return inetSocketAddress.getHostName() + ":" + inetSocketAddress.getPort();
    }

    // 字符串解析为地址
    private InetSocketAddress getInetSocketAddress(String address) {
        String[] addressArr = address.split(":");
        return new InetSocketAddress(addressArr[0], Integer.parseInt(addressArr[1]));
    }
}
